package com.lzy.filter;

import com.lzy.base.BaseInfoProperties;
import com.lzy.grace.result.ResponseStatusEnum;
import com.lzy.properties.ExcludeUrlProperties;
import com.lzy.utils.RenderErrorUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
@Slf4j
@RefreshScope
public class SecurityFilterToken extends BaseInfoProperties implements GlobalFilter, Ordered {

    @Autowired
    private ExcludeUrlProperties excludeUrlProperties; // 自定义的资源类

    // 路径匹配规则器
    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 1. 获得当前用户请求的路径url
        String url = exchange.getRequest().getURI().getPath();
        log.info("SecurityFilterToken url = {}",url);

        // 2. 获得所有需要排除校验的url list
        List<String> excludeList = excludeUrlProperties.getUrls();

        // 3.1 校验并且排除excludeList
        if(excludeList != null && !excludeList.isEmpty()){
            for (String excludeUrl : excludeList) {
                if(antPathMatcher.match(excludeUrl,url)){
                    // 如果匹配成功，则说明该路径不需要token验证，不需要拦截校验
                    log.info("当前请求的路径[{}]不需要拦截...",url);
                    return chain.filter(exchange);
                }
            }
        }
        // 3.2 排除静态资源服务static
        String fileStart = excludeUrlProperties.getFileStart();
        if(StringUtils.isNotBlank(fileStart)){
            if(antPathMatcher.match(fileStart,url)){
                return chain.filter(exchange);
            }
        }

        // 4. 代码到达此处，表示请求被拦截，需要进行校验
        log.info("当前请求的路径[{}]被拦截...",url);

        // 5. 从header中获取userId、userToken
        HttpHeaders headers = exchange.getRequest().getHeaders();
        String userId = headers.getFirst(HEADER_USER_ID);
        String userToken = headers.getFirst(HEADER_USER_TOKEN);
        // 6. 判断header中是否有token，对用户请求进行判断拦截
        if(StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(userToken)){

            //限制只能单设备登录
//            String redisToken = redis.get(REDIS_USER_TOKEN + ":" + userId);
//            if(redisToken.equals(userToken)){
//                // 匹配则放行
//                return chain.filter(exchange);
//            }
            String userIdRedis = redis.get(REDIS_USER_TOKEN + ":" + userToken);
            if(userId.equals(userIdRedis)){
                // 匹配则放行
                return chain.filter(exchange);
            }
        }
        // 默认不放行
        return RenderErrorUtils.display(exchange, ResponseStatusEnum.UN_LOGIN);
    }

    //过滤器的顺序,顺序越小则优先级越大
    @Override
    public int getOrder() {
        return 0;
    }
}
